﻿#region Using Declarations

    using System;
    using System.Linq;

    using Csla;
    using Csla.Data;
    using Csla.Server;
    using Csla.Reflection;

    using MarketPulse.BusinessLogic.Common;
    using MarketPulse.DataAccess.DataContextObjects.Production;

#endregion

namespace MarketPulse.DataAccess.Factory
{
    /// <summary>
    /// Abstracts the data access for an AreaInfo, AreaInfoList away from a Area Business Object.
    /// </summary>
    public class AreaFactory : ObjectFactory
    {

        #region Member Variables

            /// <summary>
            /// Property that stores the name of the class.
            /// </summary>
            private static readonly Type mClass = System.Reflection.MethodBase.GetCurrentMethod().DeclaringType;

            /// <summary>
            /// Property that stores the log4net logger for this class.
            /// </summary>
            private static readonly log4net.ILog mLog = log4net.LogManager.GetLogger(mClass);

        #endregion

        #region Methods

            #region Create Methods

                /// <summary>
                /// Creates new Area and returns it to the caller.
                /// </summary>
                /// <returns>The newly created Area.</returns>
                [RunLocal]
                public Area Create()
                {

                    // Create a new instance of the object
                    var area = (Area)MethodCaller.CreateInstance(typeof(Area));

                    area.Obsolete = false;

                    // Mark it as a new object
                    MarkNew(area);

                    //Check the business rules for this object
                    CheckRules(area);

                    return area;
                }

            #endregion

            #region Fetch Methods

                /// <summary>
                /// Method used to fetch a Area object from the database.
                /// </summary>
                /// <param name="criteria">The criteria (ex. GUID prim.key).</param>
                /// <returns></returns>
                public AreaInfo FetchInfo(SingleCriteria<Guid> criteria)
                {
                    try
                    {
                        using (var manager = ContextManager<MUM_dev>.GetManager(Database.BusinessSystem))
                        {
                            // Create an instance to return
                            var areaInfo = (BusinessLogic.Common.AreaInfo)MethodCaller.CreateInstance(typeof(BusinessLogic.Common.AreaInfo));

                            // Fetch the data from the database based on the criteria
                            var selectResult = manager.DataContext.UspAreaSelect(criteria.Value);

                            // Get the result
                            UspAreaSelectResult result = null;
                            result = selectResult.Single();

                            // Common properties inherited from MarketPulseBase<Area>
                            LoadProperty(areaInfo, AreaInfo.GUIDProperty, result.AreaGUID);
                            LoadProperty(areaInfo, AreaInfo.CountryGUIDProperty, (Guid)result.CountryGUID);
                            LoadProperty(areaInfo, AreaInfo.ParentAreaGUIDProperty, result.ParentAreaGUID);
                            LoadProperty(areaInfo, AreaInfo.AreaNameProperty, result.AreaName);
                            LoadProperty(areaInfo, AreaInfo.AreaCodeProperty, result.AreaCode);

                            // Make sure that CSLA knows this has changed since being instantiated
                            MarkOld(areaInfo);
                            return areaInfo;
                        }
                    }
                    catch (DataAccessException dae)
                    {
                        mLog.Error(dae.ToString());
                        throw dae;
                    }
                    catch (Exception ex)
                    {
                        mLog.Error(ex.ToString());
                        throw ex;
                    }
                }

                /// <summary>
                /// Method used to fetch Areas by specified countryGUID
                /// </summary>
                /// <param name="criteria">The criteria (ex. GUID prim.key).</param>
                /// <returns></returns>
                public MarketPulse.BusinessLogic.Common.AreaInfoList FetchInfoList(SingleCriteria<Guid> criteria)
                {
                    try
                    {
                        using (var manager = ContextManager<MUM_dev>.GetManager(Database.BusinessSystem))
                        {
                            // Create an instance to return
                            var areaInfoList = (BusinessLogic.Common.AreaInfoList)MethodCaller.CreateInstance(typeof(BusinessLogic.Common.AreaInfoList));

                            // Fetch the data from the database based on the criteria
                            var selectResult = manager.DataContext.UspAreaSelectByCountryGUID(criteria.Value);

                            // AreaInfoList is a read-only collection,
                            // so typically, when the data access is implemented in
                            // DataPortal_Fetch within the business object, the
                            // private IsReadOnly property must be set false in order to 
                            // populate the collection.  Here, within a factory 
                            // , it isn't visible so one must resort to calling the 
                            // SetIsReadOnly method provided by our parent, ObjectFactory.
                            SetIsReadOnly(areaInfoList, false);
                            foreach (UspAreaSelectByCountryGUIDResult result in selectResult)
                            {
                                BusinessLogic.Common.AreaInfo areaInfo = (BusinessLogic.Common.AreaInfo)MethodCaller.CreateInstance(typeof(BusinessLogic.Common.AreaInfo));

                                // Common properties inherited from MarketPulseBase<Area>
                                LoadProperty(areaInfo, AreaInfo.GUIDProperty, result.AreaGUID);
                                LoadProperty(areaInfo, AreaInfo.CountryGUIDProperty, (Guid)result.CountryGUID);
                                LoadProperty(areaInfo, AreaInfo.ParentAreaGUIDProperty, result.ParentAreaGUID);
                                LoadProperty(areaInfo, AreaInfo.AreaNameProperty, result.AreaName);
                                LoadProperty(areaInfo, AreaInfo.AreaCodeProperty, result.AreaCode);

                                // Mark the BranchInfo as a child element
                                MarkAsChild(areaInfo);

                                // Make sure that CSLA knows this has changed since being instantiated
                                MarkOld(areaInfo);

                                // Add the item to the list
                                areaInfoList.Add(areaInfo);
                            }

                            SetIsReadOnly(areaInfoList, true);

                            // Make sure that CSLA knows this has changed since being instantiated
                            MarkOld(areaInfoList);

                            return areaInfoList;
                        }
                    }
                    catch (DataAccessException dae)
                    {
                        mLog.Error(dae.ToString());
                        throw dae;
                    }
                    catch (Exception ex)
                    {
                        mLog.Error(ex.ToString());
                        throw ex;
                    }
                }

            #endregion

        #endregion

    }
}